package com.geodroid.action;



import java.util.ArrayList;

import android.graphics.RectF;
import android.util.Log;
import android.view.MotionEvent;

import com.geodroid.euclidian.Drawable;
import com.geodroid.euclidian.DrawableList;
import com.geodroid.euclidian.DrawableList.DrawableIterator;
import com.geodroid.euclidian.EuclidianView;

public abstract class Action {
	

	private static final String TAG = "ACTION";

	public ArrayList <Drawable> draSel=new ArrayList <Drawable>() ;
	
	public boolean isStarted = false ;
	public int nbClicked=0 ;
	RectF oldTouchedArea ; 

	
	
	/**
	 * 
	 */
	public Action() {
		this.isStarted = false;
		this.nbClicked = 0;
		this.draSel = null;
	}
	
	/**
	 * @param isStarted
	 * @param nbClicked
	 * @param draSel
	 */
	public Action(boolean isStarted, int nbClicked, ArrayList <Drawable> draSel) {
		this.isStarted = isStarted;
		this.nbClicked = nbClicked;
		this.draSel = draSel;
	}

	
	public Action(int nbC) {
		nbClicked = nbC ;
	}
	public Action(int nbClicked, ArrayList <Drawable> draSel) {
		this.isStarted = false;
		this.nbClicked = nbClicked;
		this.draSel = draSel;
	}




	public void clearSel(){
		for (Drawable d : draSel){
			d.unHighLight() ;
		}
		draSel.clear() ; 
	}

	public void dealWith(MotionEvent event, EuclidianView view){
		Log.d(TAG,"<dealWith>") ;
		int action = event.getAction();
		float x = event.getX();
		float y = event.getY();
		float width = event.getTouchMajor();
		float height = event.getTouchMinor();
		RectF touchedArea = new RectF(x-width/2,y-height/2,x+width/2,y+height/2) ;
		switch (action) {
			case MotionEvent.ACTION_DOWN:
					oldTouchedArea = touchedArea ;
					processDown(touchedArea,view) ;
					break ;
			case MotionEvent.ACTION_MOVE:
				Log.d(TAG,"validate = "+validate()) ;
					if ( !validate()){
						ArrayList<Drawable> hits = seekNearests(touchedArea,view) ;
							if (hits.size()!=0 && !draSel.contains(hits.get(0))){
							add(hits.get(0),draSel) ; 
							isStarted=true ; 
						}
					}
						Log.d(TAG,"Drasel = "+draSel.toString()) ;
						Log.d(TAG,"validate = "+validate()) ;
						if ( validate()){
							process(touchedArea,view) ;
						}
						oldTouchedArea = touchedArea ;
				break ;
			case MotionEvent.ACTION_UP :
				if ( validate()){
					processUp(touchedArea,view) ;
					isStarted = false; 
					clearSel() ;
				}
				break ;
			
			default : 
		}
		Log.d(TAG,"</dealWith>") ;
	}
	
	
	
	/**
	 * @return the draSel
	 */
	public ArrayList <Drawable> getDraSel() {
		return draSel;
	}
	/**
	 * @return the nbClicked
	 */
	public int getNbClicked() {
		return nbClicked;
	}

	/**
	 * @return the isStarted
	 */
	public boolean isStarted() {
		return isStarted;
	}

	
	protected abstract void process(RectF touchedArea, EuclidianView view) ;
	protected abstract void processDown(RectF touchedArea, EuclidianView view) ;
	protected abstract void processMove(RectF touchedArea, EuclidianView view) ;
	protected abstract void processUp(RectF touchedArea, EuclidianView view) ;

	public ArrayList<Drawable> seekNearests(RectF touchedArea, EuclidianView v){
		Log.d("ACTION", "<seekNearests>") ; 
		DrawableList drawList = v.getAllDrawableList() ; 
		ArrayList<Drawable>  result = new ArrayList<Drawable>() ; 
		DrawableIterator it = drawList.getIterator();
		while (it.hasNext()) {
			Drawable d = it.next();
			if (validate(d) && d.hits(touchedArea)){
				result.add(d) ; 
			}
		}
		return result; 
	}

	public void add(Drawable d, ArrayList<Drawable>  draSel2){
		d.highLight() ;
		draSel2.add(d) ; 
	}
	/**
	 * @param draSel the draSel to set
	 */
	public void setDraSel(ArrayList <Drawable> draSel) {
		this.draSel = draSel;
	}

	/**
	 * @param nbClicked the nbClicked to set
	 */
	public void setNbClicked(int nbClicked) {
		this.nbClicked = nbClicked;
	}

	/**
	 * @param isStarted the isStarted to set
	 */
	public void setStarted(boolean isStarted) {
		this.isStarted = isStarted;
	}
	
	public boolean validate(){
		return (draSel!=null && nbClicked == draSel.size()) ;
	} 

	public abstract boolean validate(Drawable d) ;
	
	
};
